import { defineStore } from 'pinia'
import { nextTick, isRef } from 'vue'
import axios from 'axios'

export var globalDomTree = {
    tag: 'div',
    attr: {
        id: 'canvas',
        name: 'canvas',
        style: {},
        class: {
            'web-page': true,
            highlighted: true
        },
        ClickFunctions: {},
        DoubleClickFunctions: {},
        MouseDownFunctions: {},
        MouseUpFunctions: {},
        HoverFunctions: {},
        MouseLeaveFunctions: {},
        layer: 0,
        key: false
    },
    children: [],
    parentId: null
}
export var copyJs = { copyDomTreeMap: '' }
export var domTreeMap = {}
export const styleDefault = {
    height: '',
    width: '',
    left: '',
    top: '',
    margin: '',
    padding: '',
    borderRadius: '',
    borderWidth: '',
    borderStyle: '',
    borderColor: '',
    position: 'relative',
    display: '',
    backgroundColor: '',
    color: '',
    fontFamily: '',
    fontSize: '',
    fontStyle: '',
    fontWeight: '',
    textAlign: 'center',
    alignItems: 'center',
    justifyContent: 'center',
    textDecoration: '',
    textDecorationStyle: '',
    textTransform: '',
    textIndent: '',
    letterSpacing: '0px',
    lineHeight: '20px',
    opacity: 1,
    boxShadow: '0px 0px 10px 0px #000000',
    backgroundColor: '#FFFFFF',
    transform: 'rotateX(0deg) rotateY(0deg) rotateZ(0deg)'
}

export const useDesignStore = defineStore('design', {
    state: () => ({
        currentDomPointer: {
            tag: 'div',
            attr: {
                id: '',
                name: '',
                style: {},
                class: {},
                layer: 0,
                key: false
            },
            children: [],
            parentId: null
        },
        trigger: {
            elMenu: false,
            canvas: false,
            elStyle: false
        },
        count: 1,
        disDelete: ['p', 'input', 'a', 'button'],
        disabled: false,
        project_id: '-1',
        interActive: {
            interActiveName: 'Select Target',
            interActiveTrigger: 'Click',
            interActiveCommand: 'Move'
        },
        template: {
            move: {
                relative: true,
                slowMotion: 'linear',
                duration: '',
                delay: '',
                timer: null,
                left: '',
                top: ''
            },
            zoom: {
                relative: true,
                slowMotion: 'linear',
                duration: '',
                delay: '',
                timer: null,
                width: '',
                height: ''
            },
            rotate: {
                relative: true,
                slowMotion: 'linear',
                duration: '',
                delay: '',
                timer: null,
                rotateX: '',
                rotateY: '',
                rotateZ: ''
            }
        },
        lastHoverId: '-1',
        editCss: true,
        functionIsOk: true,
        labels: ['div', 'span', 'button', 'input', 'a', 'p'],
        autoSaveIsOK: false
    }),
    actions: {
        rerender(target = 'canvas') {
            if (target === 'all') {
                Object.keys(this.trigger).forEach((key) => {
                    this.trigger[key] = !this.trigger[key]
                })
            } else {
                this.trigger[target] = !this.trigger[target]
            }
        },
        getAllClassName(classNames, classStatus) {
            let className = {}
            classNames.forEach((item) => {
                if (item !== '') {
                    className[item] = true
                }
            })
            Object.keys(classStatus).forEach((item) => {
                className[item] = classStatus[item]
            })
            let t = ''
            for (let key in className) {
                if (className[key]) {
                    t = t + ' ' + key
                }
            }
            return t.trim()
        },
        updateClass(node, classStatus) {
            // 删除原节点的 hover highlighted 样式
            this.currentDomPointer.attr.class = this.getAllClassName(
                this.currentDomPointer.attr.class.split(' '),
                {
                    hover: false,
                    highlighted: false
                }
            )
            // 更新 currentDomPointer，指向当前节点
            this.currentDomPointer = node
            this.currentDomPointer.attr.class = this.getAllClassName(
                this.currentDomPointer.attr.class.split(' '),
                classStatus
            )
        },
        getDefaultStyle(tag) {
            switch (tag) {
                case 'div': {
                    return {
                        width: '100%',
                        height: '100%',
                        padding: '20px 20px 20px 20px',
                        borderWidth: '2px',
                        borderStyle: 'solid',
                        borderColor: '#808080'
                    }
                }
                case 'button': {
                    return {
                        color: '#000000',
                        backgroundColor: 'buttonface',
                        paddingBlock: '1px',
                        paddingInline: '6px',
                        borderWidth: '2px',
                        borderStyle: 'outset',
                        borderColor: '#000000',
                        borderImage: 'initial'
                    }
                }
                case 'input': {
                    return {
                        width: '200px',
                        padding: '1px 1px 1px 1px',
                        paddingBlock: '1px',
                        paddingInline: '2px',
                        borderWidth: '2px',
                        borderStyle: 'inset',
                        borderColor: '#767676'
                    }
                }
                case 'a': {
                    return {
                        color: '#0000FF',
                        cursor: 'pointer',
                        textDecoration: 'underline'
                    }
                }
                case 'p': {
                    return {
                        color: '#000000',
                        cursor: 'pointer'
                    }
                }
                default: {
                    return {
                        width: '',
                        height: '',
                        padding: ''
                    }
                }
            }
        },
        addDom(tag) {
            if (typeof this.currentDomPointer.children[0] === 'string') {
                this.currentDomPointer.children.shift()
            }
            const node = {
                tag: tag,
                attr: {
                    id: tag + this.count,
                    name: tag + this.count,
                    onclick: this.focusOnDom,
                    onmousedown: this.mouseDownDom,
                    onmouseup: this.mouseUpDom,
                    onmouseenter: this.hoverDom,
                    onmouseleave: this.leaveDom,
                    ClickFunctions: {},
                    MouseDownFunctions: {},
                    MouseUpFunctions: {},
                    HoverFunctions: {},
                    MouseLeaveFunctions: {},
                    style: {
                        ...styleDefault,
                        ...this.getDefaultStyle(tag)
                    },
                    class: {
                        hover: false,
                        highlighted: false
                    },
                    layer: this.currentDomPointer.attr.layer + 1
                },
                children: [tag],
                parentId: this.currentDomPointer.attr.id,
                template: {
                    move: {},
                    zoom: {},
                    rotate: {}
                }
            }
            if (tag === 'input') {
                node.attr.placeholder = '请在右侧编辑文字'
                node.attr.style.cursor = 'not-allowed'
                node.attr.type = 'text'
            }
            domTreeMap[node.attr.id] = node
            this.currentDomPointer.children.push(node)
            this.count += 1
            this.rerender()
            nextTick(() => {
                document.getElementById(node.attr.id).click()
            })
        },
        removeDom(id) {
            // find parent
            const parentId = domTreeMap[id].parentId
            const parent = domTreeMap[parentId]
            // remove
            parent.children = parent.children.filter(
                (item) => item.attr.id != id
            )
            if (parent.attr.id !== 'canvas' && parent.children.length === 0) {
                parent.children.push(parent.tag)
            }

            // click
            this.rerender('all')
            nextTick(() => {
                document.getElementById(parentId).click()
            })
        },
        addFunction(name) {
            const interActiveTrigger =
                this.interActive.interActiveTrigger + 'Functions'
            // templateFunction('move', ['left', 'top'])"
            var attr = []
            if (name === 'Move') {
                attr = ['left', 'top']
            } else if (name === 'Zoom') {
                attr = ['width', 'height']
            } else {
                attr = ['rotateX', 'rotateY', 'rotateZ']
            }
            this.currentDomPointer.attr[interActiveTrigger][
                name.toLowerCase()
            ] = attr
        },
        focusOnDom(event) {
            // focus
            const t_id = event.target.id
            if (t_id in domTreeMap && t_id !== this.currentDomPointer.attr.id) {
                const node = domTreeMap[t_id]
                // 添加高亮样式
                this.updateClass(node, {
                    highlighted: true,
                    hover: false
                })
            }
            if (!this.editCss && t_id in domTreeMap) {
                // 用户自定义函数
                const ClickFunctionTriggers = Object.keys(
                    this.currentDomPointer.attr.ClickFunctions
                )
                ClickFunctionTriggers.forEach((item) => {
                    this.templateFunction(
                        item,
                        this.currentDomPointer.attr.ClickFunctions[item],
                        t_id,
                        'ClickFunctions'
                    )
                })
                if (ClickFunctionTriggers.length === 0) {
                    this.trigger['canvas'] = !this.trigger['canvas']
                    this.trigger['elStyle'] = !this.trigger['elStyle']
                }
            } else if (this.editCss) {
                this.trigger['canvas'] = !this.trigger['canvas']
                this.trigger['elStyle'] = !this.trigger['elStyle']
            }
            event.stopPropagation()
        },
        mouseDownDom(event) {
            const t_id = event.target.id
            const MouseDownFunctionTriggers = Object.keys(
                domTreeMap[t_id].attr.MouseDownFunctions
            )
            if (
                !this.editCss &&
                MouseDownFunctionTriggers.length !== 0 &&
                t_id in domTreeMap
            ) {
                // 用户自定义函数
                MouseDownFunctionTriggers.forEach((item) => {
                    this.templateFunction(
                        item,
                        domTreeMap[t_id].attr.MouseDownFunctions[item],
                        t_id,
                        'MouseDownFunctions'
                    )
                })
            }
            event.stopPropagation()
        },
        mouseUpDom(event) {
            const t_id = event.target.id
            if (!this.editCss) {
                const MouseUpFunctionTriggers = Object.keys(
                    domTreeMap[t_id].attr.MouseUpFunctions
                )
                if (
                    MouseUpFunctionTriggers.length !== 0 &&
                    t_id in domTreeMap
                ) {
                    // 用户自定义函数
                    MouseUpFunctionTriggers.forEach((item) => {
                        this.templateFunction(
                            item,
                            domTreeMap[t_id].attr.MouseUpFunctions[item],
                            t_id,
                            'MouseUpFunctions'
                        )
                    })
                }
                this.focusOnDom(event)
            }
            event.stopPropagation()
        },
        // doubleClickDom(event) {
        //     const t_id = event.target.id
        //     const DoubleClickFunctionTriggers = Object.keys(
        //         domTreeMap[t_id].attr.DoubleClickFunctions
        //     )
        //     if (
        //         DoubleClickFunctionTriggers.length !== 0 &&
        //         t_id in domTreeMap
        //     ) {
        //         // 用户自定义函数
        //         DoubleClickFunctionTriggers.forEach((item) => {
        //             this.templateFunction(
        //                 item,
        //                 domTreeMap[t_id].attr.DoubleClickFunctions[item],
        //                 t_id
        //             )
        //         })
        //     }
        //     event.stopPropagation()
        // },
        hoverDom(event) {
            const t_id = event.target.id
            if (!this.editCss && t_id !== this.lastHoverId) {
                const HoverFunctionTriggers = Object.keys(
                    domTreeMap[t_id].attr.HoverFunctions
                )
                if (HoverFunctionTriggers.length !== 0 && t_id in domTreeMap) {
                    // 用户自定义函数
                    HoverFunctionTriggers.forEach((item) => {
                        this.templateFunction(
                            item,
                            domTreeMap[t_id].attr.HoverFunctions[item],
                            t_id,
                            'HoverFunctions'
                        )
                    })
                    this.lastHoverId = t_id
                }
            }
            event.stopPropagation()
        },
        leaveDom(event) {
            this.lastHoverId = '-1'
            const t_id = event.target.id
            const LeaveFunctionTriggers = Object.keys(
                domTreeMap[t_id].attr.MouseLeaveFunctions
            )
            if (
                !this.editCss &&
                LeaveFunctionTriggers.length !== 0 &&
                t_id in domTreeMap
            ) {
                // 用户自定义函数
                LeaveFunctionTriggers.forEach((item) => {
                    this.templateFunction(
                        item,
                        domTreeMap[t_id].attr.MouseLeaveFunctions[item],
                        t_id,
                        'MouseLeaveFunctions'
                    )
                })
            }
            event.stopPropagation()
        },
        templateFunction(trigger, attr, t_id, funcName) {
            // 'move', ['left', 'top'],
            // 'resize', ['width', 'height']
            // 'rotate', ['rotateX(..deg)', 'rotateY(..deg)', 'rotateZ(..deg)']
            this.functionIsOk = false
            const move = { ...domTreeMap[t_id].template[trigger][funcName] }
            setTimeout(() => {
                var current = []
                if (trigger === 'rotate') {
                    current = domTreeMap[t_id].attr.style.transform.split(' ') // rotateX(45deg)
                }
                const move_every_step = []
                // 时间
                var number_copies = 100
                if (move.duration === '0') {
                    number_copies = 1
                }
                // 速度
                var speed = 1
                if (move.slowMotion === 'decelerate') {
                    speed = 10
                }
                // every_step
                for (var i = 0; i < attr.length; i++) {
                    if (trigger === 'rotate') {
                        current[i] = parseInt(
                            current[i].split('(')[1].split('deg')[0]
                        )
                    } else {
                        current[i] = parseInt(
                            domTreeMap[t_id].attr.style[attr[i]].replace(
                                '%',
                                ''
                            )
                        )
                        if (isNaN(current[i])) {
                            current[i] = 0
                        }
                    }
                    if (current[i] === 0 || move.relative) {
                        move_every_step[i] =
                            parseInt(move[attr[i]]) / number_copies
                    } else {
                        move_every_step[i] =
                            (parseInt(move[attr[i]]) - current[i]) /
                            number_copies
                    }
                }
                // current_left move_left_distance
                clearInterval(move.timer)
                move.timer = setInterval(() => {
                    number_copies -= speed
                    // every_step
                    if (trigger === 'rotate') {
                        var rotate = ''
                        for (var i = 0; i < attr.length; i++) {
                            current[i] += move_every_step[i] * speed
                            rotate =
                                rotate +
                                attr[i] +
                                '(' +
                                current[i] +
                                'deg)' +
                                ' '
                        }
                        domTreeMap[t_id].attr.style.transform = rotate.trim()
                    } else {
                        for (var i = 0; i < current.length; i++) {
                            current[i] += move_every_step[i] * speed
                            domTreeMap[t_id].attr.style[attr[i]] =
                                current[i] + '%'
                        }
                    }
                    this.trigger['canvas'] = !this.trigger['canvas']
                    this.trigger['elStyle'] = !this.trigger['elStyle']
                    if (number_copies <= 0) {
                        clearInterval(move.timer)
                        setTimeout(() => {
                            this.functionIsOk = true
                        }, 500)
                    }
                    if (move.slowMotion === 'accelerate') {
                        speed += 1
                        if (speed > number_copies) {
                            speed = number_copies
                        }
                    }
                    if (move.slowMotion === 'decelerate' && speed != 1) {
                        speed -= 1
                    }
                }, move.duration / number_copies)
            }, move.delay)
        },
        loadDom(dom, count) {
            globalDomTree.children = dom.children
            const newDomTreeMap = {}
            this.reconstructDomTreeMap(dom, newDomTreeMap)
            domTreeMap = newDomTreeMap
            this.count = count
        },
        reconstructDomTreeMap(dom, treeMap) {
            // 构建映射表
            treeMap[dom.attr.id] = dom
            // 绑定默认函数
            dom.attr.onClick = this.focusOnDom
            dom.attr.onmousedown = this.mouseDownDom
            dom.attr.onmouseup = this.mouseUpDom
            dom.attr.onmouseenter = this.hoverDom
            dom.attr.onmouseleave = this.leaveDom
            const children = dom.children
            for (let i = 0; i < children.length; i++) {
                if (typeof children[0] === 'string') {
                    continue
                }
                this.reconstructDomTreeMap(children[i], treeMap)
            }
        },
        eraseDefault(dom) {
            const copyDom = {
                ...dom
            }
            // copyDom.attr.onClick = ''
            // copyDom.attr.onmousedown = ''
            // copyDom.attr.onmouseup = ''
            // copyDom.attr.onmouseenter = ''
            // copyDom.attr.onmouseleave = ''
            copyDom.children = []
            const children = dom.children
            for (let i = 0; i < children.length; i++) {
                if (typeof children[0] === 'string') {
                    copyDom.children.push(children[i])
                    continue
                }
                const cCopyDom = this.eraseDefault(children[i])
                copyDom.children.push(cCopyDom)
            }
            return copyDom
        },
        jsToCss() {
            this.editCss = true
            this.loadDom(copyJs.copyDomTreeMap, this.count)
            domTreeMap['canvas'] = globalDomTree
            domTreeMap[this.currentDomPointer.attr.id].attr.class +=
                ' highlighted'
            this.currentDomPointer = domTreeMap[this.currentDomPointer.attr.id]
            this.rerender('all')
        },
        getHtmlAll() {
            const htmlHead =
                "<!DOCTYPE html><html><head><title>canvas</title></head><body><div style='height: 560px; margin: 0 auto; margin-top: 20px; padding: 20px; position: relative; text-align: center; box-shadow: 0 0 .5em 0 #000000;'>"
            var htmlContent = document
                .getElementById('canvas')
                .innerHTML.replaceAll('width: 100%;', '')
                .replaceAll('height: 100%', 'height: 90%')
            return htmlHead + htmlContent + '</div></body></html>'
        },
        exportStyleSheet(data) {
            return new Promise((resolve, reject) => {
                axios
                    .post(
                        'api/project-design/exportStyleSheet/',
                        JSON.stringify(data),
                        {
                            headers: {
                                'Content-Type': 'application/json'
                            }
                        }
                    )
                    .then((response) => {
                        resolve(response.data)
                    })
                    .catch((error) => {
                        reject(error)
                        console.log(error)
                    })
            })
        },
        deleteStyleSheet(data) {
            return new Promise((resolve, reject) => {
                axios
                    .post(
                        'api/project-design/deleteStyleSheet/',
                        JSON.stringify(data),
                        {
                            headers: {
                                'Content-Type': 'application/json'
                            }
                        }
                    )
                    .then((response) => {
                        resolve(response.data)
                    })
                    .catch((error) => {
                        reject(error)
                        console.log(error)
                    })
            })
        },
        getAllStyleSheets() {
            return new Promise((resolve, reject) => {
                axios
                    .get('api/project-design/getAllStyleSheets/')
                    .then((response) => {
                        resolve(response.data)
                    })
                    .catch((error) => {
                        reject(error)
                        console.log(error)
                    })
            })
        },
        exportPageCode(data) {
            return new Promise((resolve, reject) => {
                axios
                    .post(
                        'api/project-design/exportPageCode/',
                        JSON.stringify(data),
                        {
                            headers: {
                                'Content-Type': 'application/json'
                            }
                        }
                    )
                    .then((response) => {
                        resolve(response.data)
                    })
                    .catch((error) => {
                        reject(error)
                        console.log(error)
                    })
            })
        },
        getPageCode(project_id) {
            return new Promise((resolve, reject) => {
                axios
                    .get(
                        `api/project-design/getPageCode/?project_id=${project_id}`
                    )
                    .then((response) => {
                        resolve(response.data)
                    })
                    .catch((error) => {
                        reject(error)
                        console.log(error)
                    })
            })
        }
    }
})
